﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace RQX.Common.Web.Tools
{
    public static class ObjectExtention
    {
        public static bool IsNotNullOrEmpty(this string str)
        {
            return !string.IsNullOrEmpty(str);
        }

        /// <summary>
		/// 转为json字符串
		/// </summary>
		/// <param name="obj"></param>
		/// <returns></returns>
		public static string ToJson(this Object obj)
        {
            String str;
            if (obj == null) return string.Empty;
            if (obj is String || obj is Char)//如果是字符串或字符直接返回
            {
                str = obj.ToString();
            }
            else//否则序列为json字串
            {
                var serializerSettings = new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                    DateTimeZoneHandling = DateTimeZoneHandling.Local,
                    DateFormatString = "yyyy-MM-dd HH:mm:ss"
                    //ContractResolver = new CamelCasePropertyNamesContractResolver()
                };
                str = JsonConvert.SerializeObject(obj, Formatting.None, serializerSettings);
            }
            return str;
        }

        public static IEnumerable<TOut> CopyToList<TOut>(this object objSource, IEnumerable<TOut> objTarget, params string[] ignoredProperties)
        {
            try
            {
                var sourceList = objSource as IEnumerable<object>;
                sourceList.ForEach(source =>
                {
                    var obj = default(TOut);
                    objTarget.Append(source.CopyTo(obj, ignoredProperties));
                });
                return objTarget;
            }
            catch (Exception ex)
            {
                throw new Exception("复制失败，请手工赋值" + ex.Message);
            }

        }

        /// <summary>
        /// 对象属性复制
        /// </summary>
        /// <typeparam name="TOut">输出类型</typeparam>
        /// <param name="objSource">输入</param>
        /// <param name="objTarget">输出</param>
        /// <param name="ignoredProperties"><paramref name="objTarget"/> 所忽略复制的属性</param>
        /// <returns></returns>
        public static TOut CopyTo<TOut>(this object objSource, TOut objTarget, params string[] ignoredProperties)
        {
            try
            {
                TOut tOut = objTarget;
                var tInType = objSource.GetType();
                foreach (var itemOut in tOut.GetType().GetProperties())
                {
                    if (ignoredProperties.Contains(itemOut.Name)) continue;
                    var itemIn = tInType.GetProperty(itemOut.Name);//根据属性名称来得到对象的属性信息
                    if (itemIn != null)
                    {
                        try
                        {
                            itemOut.SetValue(tOut, itemIn.GetValue(objSource));//从（tIn）中获取属性值并赋值给StudentSecond（tOut）对象
                        }
                        catch
                        {

                        }
                    }
                }
                return tOut;
            }
            catch (Exception ex)
            {
                throw new Exception("复制失败，请手工赋值" + ex.Message);
            }

        }

        /// <summary>
        /// 对象属性复制
        /// </summary>
        /// <typeparam name="TTarget">输出类型</typeparam>
        /// <typeparam name="TSource">源类型</typeparam>
        /// <param name="objTarget">输入</param>
        /// <param name="objSource">输出</param>
        /// <param name="ignoredProperties"><paramref name="objSource"/> 所忽略复制的属性</param>
        /// <returns></returns>
        public static TTarget CopyFrom<TTarget, TSource>(this TTarget objTarget, TSource objSource, params string[] ignoredProperties)
        {
            try
            {
                TTarget tOut = objTarget;
                var tInType = objSource.GetType();
                foreach (var itemOut in tOut.GetType().GetProperties())
                {
                    if (ignoredProperties.Contains(itemOut.Name)) continue;
                    var itemIn = tInType.GetProperty(itemOut.Name);//根据属性名称来得到对象的属性信息
                    if (itemIn != null)
                    {
                        var value = itemIn.GetValue(objSource);
                        if (value != null)
                        {
                            itemOut.SetValue(tOut, value);
                        }
                    }
                }
                return tOut;
            }
            catch (Exception ex)
            {
                throw new Exception("复制失败，请手工赋值" + ex.Message);
            }

        }
        /// <summary>
        /// 获取对象属性对应的值
        /// </summary>
        /// <param name="info"></param>
        /// <param name="field">属性名称</param>
        /// <returns></returns>
        public static object GetPropertyValue(this object info, string field)
        {
            if (info == null) return null;
            Type t = info.GetType();
            IEnumerable<PropertyInfo> property = from pi in t.GetProperties() where pi.Name.ToLower() == field.ToLower() select pi;
            if (property.Count() == 0)
            {
                throw new Exception("获取属性值错误，没有对应的属性");
            }
            return property.First().GetValue(info, null);
        }

        public static string GetLastString(this string[] list)
        {
            if (list.Length > 0)
            {
                return list[^1];
            }
            else
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 包含其中一项则返回true
        /// </summary>
        /// <param name="Str"></param>
        /// <param name="filterList"></param>
        /// <returns></returns>
        public static bool Contains(this string Str, params string[] filterList)
        {
            foreach (var filter in filterList)
            {
                if (Str.Contains(filter)) return true;
            }
            return false;
        }
        /// <summary>
        /// 全部包含才返回true
        /// </summary>
        /// <param name="Str"></param>
        /// <param name="filterList"></param>
        /// <returns></returns>
        public static bool ContainsAll(this string Str, params string[] filterList)
        {
            foreach (var filter in filterList)
            {
                if (!Str.Contains(filter)) return false;
            }
            return true;
        }

        public static void ForEach<T>(this IEnumerable<T> query, Action<T> action)
        {
            foreach (var item in query)
            {
                action(item);
            }
        }

        public static T Find<T>(this IEnumerable<T> query, Func<T, bool> func)
        {
            foreach (var item in query)
            {
                if (func(item))
                {
                    return item;
                }
            }
            return default;
        }

        /// <summary>
        /// 通过名称获取type
        /// </summary>
        /// <param name="fullName"></param>
        /// <returns></returns>
        public static Type GetCurrentType(this string fullName)
        {
            return AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(a => a.GetTypes())
                        .Where(u => fullName.Equals(u.FullName))
                        .ToList().FirstOrDefault();
        }

        public static T DeepCopy<T>(this object obj)
        {

            if (obj is String || obj is Char)//如果是字符串或字符直接返回
            {
                return (T)obj;
            }
            else
            {
                return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj), new JsonSerializerSettings() { DateTimeZoneHandling = DateTimeZoneHandling.Local });
            }
        }

        public static bool IsIn(this string str, params string[] data)
        {
            foreach (var item in data)
            {
                if (str == item)
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsNotIn(this string str, params string[] data)
        {
            foreach (var item in data)
            {
                if (str == item)
                {
                    return false;
                }
            }
            return true;
        }

        public static bool IsIn(this int integer, params int[] data)
        {
            foreach (var item in data)
            {
                if (integer == item)
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsNotIn(this int integer, params int[] data)
        {
            foreach (var item in data)
            {
                if (integer == item)
                {
                    return false;
                }
            }
            return true;
        }


        public static string RemoveEndStr(this string baseStr, params string[] removeStrList)
        {
            if (baseStr == null)
            {
                return null;
            }

            if (baseStr == string.Empty)
            {
                return string.Empty;
            }

            if (removeStrList.IsNullOrEmpty())
            {
                return baseStr;
            }

            foreach (var removeStr in removeStrList)
            {
                if (baseStr.EndsWith(removeStr))
                {
                    return baseStr.Left(baseStr.Length - removeStr.Length);
                }
            }

            return baseStr;
        }

        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }

        public static bool IsNullOrEmpty<T>(this ICollection<T> source)
        {
            return source == null || source.Count <= 0;
        }
        public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
        {
            return source == null || source.Count() <= 0;
        }

        public static bool IsNull(this object obj)
        {
            return obj == null;
        }

        public static string Left(this string str, int len)
        {
            if (str == null || str.Length < len)
            {
                return str;
            }

            return str.Substring(0, len);
        }


    }
}
